<?php

namespace app\models;

use yii\db\Query;

/**
 * @property int created_at
 * @property int source_id
 * @property int type_id
 * @property int user_id
 * @property int status
 * @property int|string creator_id
 */
class Task extends \yii\db\ActiveRecord
{
    public function rules()
    {
        return [
            [['source_id','name','content','user_id','type_id','status','ended_at'], 'required'],
            [['source_id','user_id','type_id','status','ended_at'], 'integer'],
            [['content','name'], 'string'],
        ];
    }

    public function extraFields()
    {
        $fields['task_flow'] = function ($model){
            return $model->taskFlow;
        };

        $fields['user_name'] = function ($model){
            return $model->user->name;
        };

        $fields['creator_name'] = function ($model){
            return $model->creator->name;
        };

        $fields['department_name'] = function ($model){
            return $model->user->department->name;
        };

        $fields['branch_name'] = function ($model){
            return $model->user->branch->name;
        };

        return $fields;
    }

    public function getTaskFlow(){
        return $this->hasMany(TaskFlow::class,['task_id'=>'id']);
    }

    public function getUser(){
        return $this->hasOne(User::class,['id'=>'user_id']);
    }

    public function getCreator(){
        return $this->hasOne(User::class,['id'=>'creator_id']);
    }

    // 产生根节点，分公司节点
    public static function generateRootNode(){
        $query = new Query();
        $query = $query->select(['b.id as branch_id','COUNT(t.id) as task_num'])
            ->from('{{%task}} as t')
            ->leftJoin('{{%user}} as u','u.id = t.user_id')
            ->leftJoin('{{%department}} as d','d.id = u.department_id')
            ->leftJoin('{{%branch}} as b','b.id = d.branch_id')
            ->where('t.status=1')
            ->groupBy(['b.id']);
        // having 是对汇总字段进行筛选，所以，having发生在分组之后。

        // 以到期时间为条件，按branch.id分组汇总，三种到期时间条件：
        // 未到期
        $queryClone = clone $query;
        $og = $queryClone
            ->andWhere('t.ended_at - '.time().'>0')
            ->all();
        // 快到期
        $queryClone = clone $query;
        $we = $queryClone
            ->andWhere('t.ended_at - '.time().'>0')
            ->andWhere('t.ended_at - '.time().'<259220')->all();
        // 已到期
        $queryClone = clone $query;
        $ae = $queryClone->andWhere('t.ended_at - '.time().'<=0')->all();

        // 那么，只有符合此时间条件的记录才会被筛选
        // 定理：groupBy 的COUNT()项，恒 >= 1, 证明：groupBy 是对已有项进行分组和统计，所有的统计项均基于已经存在的分类项。只要存在，计数将必大于0
        // 索引数组转关联数组
        $arr = [
            'og'=>array_column($og,'task_num','branch_id'),
            'we'=>array_column($we,'task_num','branch_id'),
            'ae'=>array_column($ae,'task_num','branch_id'),
        ];
        // 关联数组契入node结构
        return self::convertToRootNode($arr);
    }

    private static function convertToRootNode($arr=null){
        $branches = Branch::find()->asArray()->all();
        $node = [];
        foreach ($branches as $branch){
            array_push($node,
                [
                    'level'=>'1',
                    'id'=>$branch['id'],
                    'label'=>$branch['name'],
                    'task_num'=>[
                        // 如果关联数组存在该branch_id索引，则取得该索引映射的值（即为task_num），否则为0
                        'og'=>isset($arr['og'][$branch['id']])?$arr['og'][$branch['id']]:'0',
                        'we'=>isset($arr['we'][$branch['id']])?$arr['we'][$branch['id']]:'0',
                        'ae'=>isset($arr['ae'][$branch['id']])?$arr['ae'][$branch['id']]:'0',
                    ],
                    'children'=>[]
                ]);
        }
        return $node;
    }

    // 产生二级节点，部门节点
    public static function generateLevel2Node($branch_id = 1){
        $query = new Query();
        $query = $query->select(['d.id as department_id','COUNT(t.id) as task_num'])
            ->from('{{%task}} as t')
            ->leftJoin('{{%user}} as u','u.id = t.user_id')
            ->leftJoin('{{%department}} as d','d.id = u.department_id')
            ->leftJoin('{{%branch}} as b','b.id = d.branch_id')
            ->Where(['b.id'=>$branch_id])
            ->andwhere('t.status=1')
            ->groupBy(['d.id']);

        // 以到期时间为条件，按branch.id分组汇总，三种到期时间条件：
        // 未到期
        $queryClone = clone $query;
        $og = $queryClone
            ->andWhere('t.ended_at - '.time().'>0')
            ->all();
        // 快到期
        $queryClone = clone $query;
        $we = $queryClone
            ->andWhere('t.ended_at - '.time().'>0')
            ->andWhere('t.ended_at - '.time().'<259220')->all();
        // 已到期
        $queryClone = clone $query;
        $ae = $queryClone->andWhere('t.ended_at - '.time().'<=0')->all();

        // 那么，只有符合此时间条件的记录才会被筛选
        // 定理：groupBy 的COUNT()项，恒 >= 1, 证明：groupBy 是对已有项进行分组和统计，所有的统计项均基于已经存在的分类项。只要存在，计数将必大于0
        // 索引数组转关联数组
        $arr = [
            'og'=>array_column($og,'task_num','department_id'),
            'we'=>array_column($we,'task_num','department_id'),
            'ae'=>array_column($ae,'task_num','department_id'),
        ];

        $node = self::convertToLevel2Node($arr,$branch_id);
        return $node;
    }

    private static function convertToLevel2Node($arr,$branch_id){
        $items = Department::find()->asArray()->where(['branch_id'=>$branch_id])->all();
        $node = [];
        foreach ($items as $item){
            array_push($node,
                [
                    'level'=>'2',
                    'id'=>$item['id'],
                    'label'=>$item['name'],
                    'task_num'=>[
                        // 如果关联数组存在该branch_id索引，则取得该索引映射的值（即为task_num），否则为0
                        'og'=>isset($arr['og'][$item['id']])?$arr['og'][$item['id']]:'0',
                        'we'=>isset($arr['we'][$item['id']])?$arr['we'][$item['id']]:'0',
                        'ae'=>isset($arr['ae'][$item['id']])?$arr['ae'][$item['id']]:'0',
                    ],
                    'children'=>[]
                ]);
        }
        return $node;
    }

    // 产生三级级节点，即员工节点
    public static function generateLevel3Node($department_id = 1){
        $query = new Query();
        $query = $query->select(['u.id as user_id','COUNT(t.id) as task_num'])
            ->from('{{%task}} as t')
            ->leftJoin('{{%user}} as u','u.id = t.user_id')
            ->leftJoin('{{%department}} as d','d.id = u.department_id')
            ->Where(['d.id'=>$department_id])
            ->andwhere('t.status=1')
            ->groupBy(['u.id']);

        // 以到期时间为条件，按branch.id分组汇总，三种到期时间条件：
        // 未到期
        $queryClone = clone $query;
        $og = $queryClone
            ->andWhere('t.ended_at - '.time().'>0')
            ->all();
        // 快到期
        $queryClone = clone $query;
        $we = $queryClone
            ->andWhere('t.ended_at - '.time().'>0')
            ->andWhere('t.ended_at - '.time().'<259220')->all();
        // 已到期
        $queryClone = clone $query;
        $ae = $queryClone->andWhere('t.ended_at - '.time().'<=0')->all();

        // 那么，只有符合此时间条件的记录才会被筛选
        // 定理：groupBy 的COUNT()项，恒 >= 1, 证明：groupBy 是对已有项进行分组和统计，所有的统计项均基于已经存在的分类项。只要存在，计数将必大于0
        // 索引数组转关联数组
        $arr = [
            'og'=>array_column($og,'task_num','user_id'),
            'we'=>array_column($we,'task_num','user_id'),
            'ae'=>array_column($ae,'task_num','user_id'),
        ];

        $node = self::convertToLevel3Node($arr,$department_id);
        return $node;
    }

    private static function convertToLevel3Node($arr,$department_id){
        $items = User::find()->asArray()->where(['department_id'=>$department_id])->all();
        $node = [];
        foreach ($items as $item){
            array_push($node,
                [
                    'level'=>'3',
                    'id'=>$item['id'],
                    'label'=>$item['name'],
                    'task_num'=>[
                        // 如果关联数组存在该branch_id索引，则取得该索引映射的值（即为task_num），否则为0
                        'og'=>isset($arr['og'][$item['id']])?$arr['og'][$item['id']]:'0',
                        'we'=>isset($arr['we'][$item['id']])?$arr['we'][$item['id']]:'0',
                        'ae'=>isset($arr['ae'][$item['id']])?$arr['ae'][$item['id']]:'0',
                    ],
                    'children'=>[]
                ]);
        }
        return $node;
    }

    // 产生四级级节点，即任务节点
    public static function generateLevel4Node($user_id = 1){
        $items = self::find()->asArray()->where(['user_id'=>$user_id])->all();
        $node = [];
        foreach ($items as $item){
            array_push($node, [
                'level'=>'4',
                'id'=>$item['id'],
                'label'=>$item['name'],
                'content'=>$item['content'],
                'ended_at'=>date('Y-m-d',$item['ended_at']),
                'day_remaining'=>(int)(($item['ended_at']-time())/86400),
                'children'=>[]
            ]);
        }
        return $node;
    }

    // 产生五级节点，即任务流水节点
    public static function generateLevel5Node($task_id = 1){
        $items = TaskFlow::find()->asArray()->where(['task_id'=>$task_id])->all();
        $node = [];
        foreach ($items as $item){
            array_push($node, [
                'level'=>'5',
                // 'children'=>[],

                'id'=>$item['id'],
                'label'=>'>>',
                'content'=>$item['content'],
                'updated_at'=>date('Y-m-d',$item['updated_at']),
            ]);
        }
        return $node;
    }
}
